home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / uemlsrc / kermit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-08-24  |  20.4 KB  |  608 lines

  1. /* kermit.c  support routines and main entry point for Uemail file transfer
  2.  * functions.  Kermit send, receive, get, put, finish, and bye supported.
  3.  * Buffer logging and direct ASCII transfer also available.  All actions are
  4.  * ASCII 7 bit files.  Transfers are made into and out of Uemail buffers.
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <osbind.h>
  9. #include <ctype.h>
  10. #include "ed.h"
  11. #include "kermit.h"
  12.  
  13.  
  14. int emacsfile;          /* if TRUE then \r become \n on ASCII transfers */
  15. char getfiln[NFILEN];   /* name for remote file get or put */
  16. char deflow[] = "XON/XOFF";
  17. static unsigned char *tsr_ptr = (char *)0x00fffa2d; /* See St internals */
  18. static long *hz_200 =  (long *)0x000004ba;
  19. int *aaddress(); /* thanks Jwahar R. Bammi for this line A code */
  20. int *aline_addr; /* Ptr to base of Aline variables */
  21. int sav_row, sav_col;
  22. int flow = DEFLO;       /* default flow control */
  23. int defbaud = 7;
  24. int bps = DEFBPS;
  25. unsigned long *hpterm;  /* HOST */
  26.  
  27. /* KERMIT CTRL command prompt for action and switch to appropriate state.
  28.  * Returns TRUE on success. !TRUE on failures.  Bound to ^_ and HELP on ST.
  29.  */
  30. kermit(flg, _n)
  31. register int flg, _n;
  32. {
  33.         static char command[9]; /* command */
  34.         register char key;
  35.         register int owf;
  36.  
  37.         owf = curwp->w_flag;            /* save for redraw */
  38.  
  39.         if ((_n=mlreply("Kermit-ST> ",command,8)) != TRUE)
  40.                 return(_n==FALSE ? FALSE : ABORT);
  41.  
  42.         /* Initialize these values */
  43.         /* Hope the first packet will get across OK */
  44.  
  45.         eol = CR;               /* EOL for outgoing packets */
  46.         quotech = '#';          /* Standard control-quote char "#" */
  47.         pad = 0;                /* No padding */
  48.         padchar = '\0';         /* Use null if any padding wanted */
  49.         timint = DEFTIME;       /* Default timeout */
  50.         parity = DEFPAR;        /* Default to no parity */
  51.         logfile = 0;            /* Capture flag */
  52.         emacsfile = 0;          /* Trans to emacs (no EOF) */
  53.         en8quote(FALSE);
  54.  
  55.         key = tolower(command[0]);
  56.         switch (key)
  57.                 {
  58.                 case 'b':               /* B = Bye */
  59.                         if(mlyesno("Logout remote")==TRUE)
  60.                                 if(gencmdsw('L')==FALSE)
  61.                                         {
  62.                                         mlwrite("Remote does not ACK BYE");
  63.                                         (*term.t_beep)();
  64.                                         return(FALSE);
  65.                                         }
  66.                         return(TRUE);   /* No update */
  67.                 case 'c':              /* C = Connect command */
  68.                         connect();
  69.                         break;
  70.                 case 'e':              /* E = transmit to GNU_EMACS command */
  71.                         if(usebuffer(NULL,NULL) != TRUE)
  72.                                 return(FALSE);
  73.                         gotobob(NULL, 1);
  74.                         update();
  75.                         mlwrite("[Transmitting %s to remote EMACS]",curbp->b_bna
  76. me);
  77.                         emacsfile = 1;
  78.                         trans();
  79.                         emacsfile = 0;
  80.                         connect();
  81.                         break;
  82.                 case 'f':               /* F = Finish */
  83.                         if(gencmdsw('F')==FALSE)
  84.                                 {
  85.                                 mlwrite("Remote does not ACK FINISH");
  86.                                 (*term.t_beep)();
  87.                                 return(FALSE);
  88.                                 }
  89.                         return(TRUE);   /* No update */
  90.                 case 'g':              /* G = Get command */
  91.                         if((_n=mlreply("Remote filename: ",getfiln,NFILEN))!=TRU
  92. E)
  93.                                 return(_n);
  94.                         if(usebuffer(NULL,NULL) != TRUE)
  95.                                 return(FALSE);
  96.                         gotoeob(NULL, 1);
  97.                         update();
  98.                         if((_n=getsw()) == FALSE)
  99.                                 {
  100.                                 (*term.t_beep)();
  101.                                 mlreply("Get failed. Type <CR>",command,2);
  102.                                 }
  103.                         break;
  104.                 case 'l':       /* L = Log session */
  105.                         if(usebuffer(NULL,NULL) != TRUE)
  106.                                 return(FALSE);
  107.                         gotoeob(NULL, 1);
  108.                         logfile = TRUE;
  109.                         connect();
  110.                         break;
  111.                 case 'r':              /* R = Receive command */
  112.                         if(usebuffer(NULL,NULL) != TRUE)
  113.                                 return(FALSE);
  114.                         gotoeob(NULL, 1);
  115.                         update();
  116.                         if((_n=recsw()) == FALSE)
  117.                                 {
  118.                                 (*term.t_beep)();
  119.                                 mlreply("Receive failed. Type <CR>",command,2);
  120.                                 }
  121.                         break;
  122.                 case 'p':               /* P = Put command */
  123.                         if((_n=mlreply("Remote filename: ",getfiln,NFILEN))!=TRU
  124. E)
  125.                                 return(_n);
  126.                 case 's':               /* S = Send command */
  127.                         if(usebuffer(NULL,NULL) != TRUE)
  128.                                 return(FALSE);
  129.                         if (key == 's')
  130.                                 strcpy(getfiln,curbp->b_bname);
  131.                         gotobob(NULL, 1);
  132.                         update();
  133.                         if((_n=sendsw()) == FALSE)
  134.                                 {
  135.                                 if (key == 's')
  136.                                         mlwrite("Send failed");
  137.                                 else
  138.                                         mlwrite("Put failed");
  139.                                 (*term.t_beep)();
  140.                                 }
  141.                         if (key == 's')
  142.                                 connect();
  143.                         break;
  144.                 case 't':              /* T = transmit command */
  145.                         if(usebuffer(NULL,NULL) != TRUE)
  146.                                 return(FALSE);
  147.                         gotobob(NULL, 1);
  148.                         update();
  149.                         mlwrite("[Transmitting: %s]",curbp->b_bname);
  150.                         trans();
  151.                         connect();
  152.                         break;
  153.                 default:
  154.                         mlwrite("Connect, Send, Receive, Get, Put, Finish, Bye\
  155. , Log, Transfer");
  156.  
  157.                         return(FALSE);
  158.                 }
  159.         /* Restore controlling tty's modes */
  160.  
  161.         owf |= WFHARD; owf |= WFMODE;
  162.         curwp->w_flag |= owf;
  163.         sgarbf = TRUE;  /* we know screen is garbage after connect */
  164.         update();
  165.         return(TRUE);
  166. }
  167.  
  168. /*
  169. *      c o n n e c t
  170. *
  171. * Establish a virtual terminal connection with the remote host, over an
  172. * assigned tty line.
  173. */
  174.  
  175. connect()
  176. {
  177.         register int c;
  178.  
  179.         setterm(REMOTE);
  180.         while (1)
  181.                 {
  182.                 if (Bconstat(2))
  183.                         if(readcon() == FALSE)
  184.                                 break;
  185.                 if (Bconstat(1))
  186.                         {
  187.                         c=readaux();
  188.                         ttputc(c);
  189.                         if (logfile)
  190.                                 {
  191.                                 if (c=='\n')
  192.                                         {
  193.                                         lnewline();
  194.                                         continue;
  195.                                         }
  196.                                 if (c=='\r')
  197.                                         continue;
  198.                                 linsert(1,c);
  199.                                 }
  200.                         }
  201.                 }
  202.         setterm(HOST);
  203.         return(FALSE);
  204. }
  205.  
  206. /* set up terminal's screen and allow it to be saved for later.
  207.  */
  208. setterm(f)
  209. int f;
  210. {
  211.         static char scrbase[0x7d10];
  212.         static unsigned char firsttime = TRUE;
  213.         extern int deskcol;
  214.  
  215.         if (hpterm == NULL)
  216.                 hpterm = Physbase();    /* init TERM screen address */
  217.         if (f == REMOTE)
  218.                 {
  219.                 Bconout(2,0x1b);        /* disable cursor */
  220.                 Bconout(2,'f');
  221.                 copy(scrbase,hpterm,0x7d00);
  222.                 if (firsttime)
  223.                         {
  224.                         aline_addr = aaddress();
  225.                         Bconout(2,0x1b);        /* clear screen */
  226.                         Bconout(2,'E');
  227.                         showhelp();
  228.                         sav_row = aline_addr[-13];/* save cursor position */
  229.                         sav_col = aline_addr[-14];
  230.                         Rsconf(defbaud,flow,-1,-1,-1,-1);
  231.                         mtwrite("[%s active at %dbps]",deflow,bps);
  232.                         firsttime = FALSE;
  233.                         }
  234.                 (*term.t_move)(sav_row,sav_col);
  235.                 Bconout(2,0x1b);        /* enable cursor */
  236.                 Bconout(2,'e');
  237.                 return(TRUE);
  238.                 }
  239.         else if (f == HOST)
  240.                 {
  241.                 sav_row = aline_addr[-13];      /* save cursor position */
  242.                 sav_col = aline_addr[-14];
  243.                 Bconout(2,0x1b);        /* disable cursor */
  244.                 Bconout(2,'f');
  245.                 copy(hpterm,scrbase,0x7d00);
  246.                 ttopen();               /* restore uemail screen */
  247.                 Bconout(2,0x1b);        /* enable cursor */
  248.                 Bconout(2,'e');
  249.                 return(TRUE);
  250.                 }
  251.         else if (f == SHOWHELP)
  252.                 {
  253.                 sav_row = aline_addr[-13];      /* save cursor position */
  254.                 sav_col = aline_addr[-14];
  255.                 Bconout(2,0x1b);                /* disable cursor */
  256.                 Bconout(2,'f');
  257.                 copy(hpterm,scrbase,0x7d00);    /* save current screen */
  258.                 showhelp();                     /* write help message */
  259.                 while(ttgetc())                 /* wait for */
  260.                         if (scancode == 0x62)   /* HELP key */
  261.                                 break;
  262.                 copy(scrbase,hpterm,0x7d00);    /* restore old screen */
  263.                 (*term.t_move)(sav_row,sav_col);
  264.                 Bconout(2,0x1b);                /* enable cursor */
  265.                 Bconout(2,'e');
  266.                 return(TRUE);
  267.                 }
  268. }
  269.  
  270. /*
  271.  * return the base address of the line A variables
  272.  * Bammi @ Case
  273.  */
  274. int *
  275. aaddress()
  276. {
  277.         asm("dc.w $A000");/* Line A trap - 0000 is init line-A  */
  278.         /* d0 and a0 now contain the address
  279.          * so we can just return and the result
  280.          * will be valid
  281.          */
  282. }
  283.  
  284. /* a mini-mlwrite for the terminal mode */
  285. /* VARARGS */
  286. mtwrite(fmt,arg1,arg2,arg3,arg4)
  287. register char *fmt;
  288. register long arg1,arg2,arg3,arg4;
  289. {
  290.         static char buf[128];
  291.  
  292.         sprintf(buf,fmt,arg1,arg2,arg3,arg4);
  293.         ttputc(0x1b);ttputc('j');       /* save cursor */
  294.         (*term.t_move)(term.t_nrow,0);
  295.         ttputc(0x1b);ttputc('l');       /* delete line */
  296.         Cconws(buf);
  297.         ttputc(0x1b);ttputc('k');       /* restore cursor */
  298.         return(TRUE);
  299. }
  300.  
  301. /* A modicum of help for the RS232 connection module */
  302. int
  303. showhelp()
  304. {
  305.         register int i;
  306.         i = 5;
  307.  
  308.         Crawio(0x1b);
  309.         Crawio('p');    /* rev video on */
  310.         (*term.t_move)(i++,17);
  311.         Cconws("                                     ");
  312.         (*term.t_move)(i++,17);
  313.         Cconws("   ALT-UNDO    return to Uemail      ");
  314.         (*term.t_move)(i++,17);
  315.         Cconws("   ALT-B       set the baud rate     ");
  316.         (*term.t_move)(i++,17);
  317.         Cconws("   ALT-C       change color          ");
  318.         (*term.t_move)(i++,17);
  319.         Cconws("   ALT-E       load an alias file    ");
  320.         (*term.t_move)(i++,17);
  321.         Cconws("   ALT-L       load a macro file     ");
  322.         (*term.t_move)(i++,17);
  323.         Cconws("   ALT-O       turn off flow control ");
  324.         (*term.t_move)(i++,17);
  325.         Cconws("   ALT-R       turn on RTS/CTS       ");
  326.         (*term.t_move)(i++,17);
  327.         Cconws("   ALT-X       turn on XON/XOFF      ");
  328.         (*term.t_move)(i++,17);
  329.         Cconws("   ALT-T       show the current time ");
  330.         (*term.t_move)(i++,17);
  331.         Cconws("   ALT-CTRL-B  send a break          ");
  332.         (*term.t_move)(i++,17);
  333.         Cconws("   ALT-CTRL-C  run a program         ");
  334.         (*term.t_move)(i++,17);
  335.         Cconws("   ALT-?       this help message     ");
  336.         (*term.t_move)(i++,17);
  337.         Cconws("   HELP        this help message     ");
  338.         (*term.t_move)(i++,17);
  339.         Cconws("                                     \r\n");
  340.         Crawio(0x1b);
  341.         Crawio('q');    /* rev video off */
  342.         return(TRUE);
  343. }
  344.  
  345. /* setbaud for RS232 (default is 1200) */
  346.  
  347. int
  348. setbaud()
  349. {
  350.         register int c;
  351.  
  352.         mtwrite("Baud rate [a/b/c/d/e] a = 300, \
  353. b = 1200, c = 2400, d = 9600, e = 19,200");
  354.         c = ttgetc();
  355.         switch(c)
  356.                 {
  357.                 case 'a':
  358.                 case 'A':
  359.                         defbaud = 9;
  360.                         bps = 300;
  361.                         Rsconf(defbaud,flow,-1,-1,-1,-1);
  362.                         mtwrite("[Baud = %dbps]",bps);
  363.                         return(TRUE);
  364.                 case 'b':
  365.                 case 'B':
  366.                         defbaud = 7;
  367.                         bps = 1200;
  368.                         Rsconf(defbaud,flow,-1,-1,-1,-1);
  369.                         mtwrite("[Baud = %dbps]",bps);
  370.                         return(TRUE);
  371.                 case 'c':
  372.                 case 'C':
  373.                         defbaud = 4;
  374.                         bps = 2400;
  375.                         Rsconf(defbaud,flow,-1,-1,-1,-1);
  376.                         mtwrite("[Baud = %dbps]",bps);
  377.                         return(TRUE);
  378.                 case 'd':
  379.                 case 'D':
  380.                         defbaud = 1;
  381.                         bps = 9600;
  382.                         Rsconf(defbaud,flow,-1,-1,-1,-1);
  383.                         mtwrite("[Baud = %dbps]",bps);
  384.                         return(TRUE);
  385.                 case 'e':
  386.                 case 'E':
  387.                         defbaud = 0;
  388.                         bps = 19200;
  389.                         Rsconf(defbaud,flow,-1,-1,-1,-1);
  390.                         mtwrite("[Baud = %dbps]",bps);
  391.                         return(TRUE);
  392.                 default:
  393.                         Rsconf(defbaud,flow,-1,-1,-1,-1);
  394.                         mtwrite("[Baud = %dbps]",bps);
  395.                         return(TRUE);
  396.                 }
  397. }
  398.  
  399. /*
  400. *      KERMIT utilities.
  401. */
  402.  
  403. /* generic command for BYE and FINish */
  404. gencmdsw(cmd)
  405. char cmd;
  406. {
  407.         int num, len;              /* Packet number, length */
  408.         packet[0] = cmd;              /* Generic command */
  409.         spack('G', 0, 1, packet);     /* Send Generic command  */
  410.  
  411.         switch(rpack(&len,&num,packet))  /* Get packet */
  412.                 {
  413.                 case 'Y':
  414.                         return(TRUE);
  415.                 case 'E':
  416.                         prerrpkt(packet);
  417.                         return(FALSE);
  418.                 default:
  419.                         return(FALSE);
  420.                 }
  421.  
  422. }
  423.  
  424. /*
  425. *      b u f i l l
  426. *
  427. * Get a bufferful of data from the buffer that's being sent.
  428. * Only control-quoting and 8-bit quoting is done;
  429. * repeat count prefixes are not handled.
  430. */
  431.  
  432. bufill(buffer)
  433. char buffer[];                    /* Buffer */
  434. {
  435.         register char t;                         /* Char read from file */
  436.         register char *buffend;          /* End of buffer pointer */
  437.         register char *buffp;              /* Pointer into buffer */
  438.         register int unprintable;              /* Is a character printable ?*/
  439.         short eolflag = FALSE;                  /* kludge for VAX */
  440.  
  441.         buffend = &buffer[spsiz-9];     /* set up end of buffer pointer */
  442.         buffp=buffer;              /* and the current position */
  443.  
  444.         while(curwp->w_dotp != curbp->b_linep)
  445.                 {
  446.                 t = lgetc(curwp->w_dotp, curwp->w_doto);
  447.                 if (curwp->w_doto == llength(curwp->w_dotp))
  448.                         {
  449.                         t = eol;
  450.                         eolflag = TRUE; /* kludge for VAX */
  451.                         }
  452.  
  453.                 unprintable = ((t<SP)||(t==DEL));
  454.  
  455.                 /* Does this char require special handling? */
  456.                 if ((unprintable) || t==quotech)
  457.                         {
  458.                         *buffp++ = quotech;       /* Quote the character */
  459.                         if (unprintable)
  460.                                 t = ctl(t);          /* and uncontrolify */
  461.                         }
  462.                 *buffp++ = t;
  463.                 if (eolflag)
  464.                         {
  465.                         eolflag = FALSE;        /* be sure it gets \r\n pair */
  466.                         *buffp++ = quotech;     /* this is for VAX/VMS */
  467.                         *buffp++ = ctl(LF);
  468.                         }
  469.                 forwchar(FALSE,1);
  470.                 /* Check length */
  471.                 if (buffp>=buffend)     /* this is how you avoid pointer */
  472.                         return((int)buffp-(int)buffer); /* subtraction */
  473.                 }                       /* not (int)(buffp-buffer) */
  474.         if (buffp == buffer)
  475.                 return(EOF);
  476.         return((int)buffp-(int)buffer); /* Handle partial buffer */
  477. }
  478.  
  479. /*
  480. *      b u f e m p
  481. *
  482. * Put data from an incoming packet into the default buffer.
  483. */
  484.  
  485. bufemp(buffer,len)
  486. char buffer[];                    /* Buffer */
  487. int len;                                /* Length */
  488. {
  489.         register int i;          /* Counter */
  490.         register char t;                /* Character holder */
  491.         register int highbit;      /* place to hold quoted highbit */
  492.  
  493.         highbit = 0;
  494.         for (i=0; i<len; i++)      /* Loop thru the data field */
  495.                 {
  496.                 t = buffer[i];            /* Get a character */
  497.                 if (t == MYQUOTE)              /* Control quote? */
  498.                         {                              /* Yes */
  499.                         t = buffer[++i];        /* Get the quoted character */
  500.                         /* Low order bits match quote char? */
  501.                         if (((t & 0177) != MYQUOTE) &&
  502.                             (!qflag || ((t & 0x7F)!=qbin)))
  503.                                 t = ctl(t);     /* No, uncontrollify it */
  504.                         }
  505.                 t |= highbit;   /* set top bit if needed */
  506.                 highbit=0;
  507.                 if (t==eol)
  508.                         {
  509.                         lnewline();
  510.                         continue;
  511.                         }
  512.                 if (t=='\n')
  513.                         continue;
  514.                 linsert(1,t);
  515.         }
  516. }
  517.  
  518. int
  519. readaux()
  520. {
  521.         int i;
  522.  
  523.         while(!Bconstat(1))     /* loop until line is ready or */
  524.                 if (i++ >= 32000)       /* time is up */
  525.                         return(FALSE);
  526.         return ((int)Bconin(1));        /* char not masked when read */
  527. }
  528.  
  529. sauxstr(buf,len)
  530. char *buf;
  531. int len;
  532. {
  533.         for(;len>0;len--)
  534.                 sendaux(*buf++);
  535. }
  536.  
  537. sendaux(c)
  538. int c;
  539. {
  540.         while(!Bcostat(1))
  541.                 {
  542.                 if (Bconstat(2))
  543.                         if (ttgetc()==0x07)
  544.                                 return(FALSE);
  545.                 }
  546.         Bconout(1,c);   /* Send character */
  547. }
  548.  
  549. /*
  550. *      p r e r r p k t
  551. *
  552. * Print contents of error packet received from remote host.
  553. */
  554. prerrpkt(msg)
  555. char *msg;
  556. {
  557.         mlwrite("ABORT: %s",msg);
  558.         return;
  559. }
  560.  
  561. en8quote(t)
  562. int t;
  563. {
  564.         qflag = t;
  565. /* no binary files allowed */
  566. }
  567.  
  568. /* tsr_ptr points to the 8 bit TSR register of the 68901
  569.  * From Jwahar R. Bammi
  570.  * send a break
  571.  * Modifies Bit 3 in the TSR (reg 23) of the Mfp
  572.  */
  573.  
  574. sendbrk()
  575. {
  576.         register long save_ssp;
  577.         register long time;
  578.  
  579.         save_ssp = Super(0L);   /* Super Mode */
  580.  
  581.         /* set bit 3 of the TSR */
  582.         *tsr_ptr |= (unsigned char)8;
  583.  
  584.         /* wait for 250 ms -- you can adjust the duration
  585.          * 250 ms seems to be almost a universal figure for break
  586.          * duration.
  587.          */
  588.         time = *hz_200 + 50;
  589.         while(*hz_200 < time)
  590.         /* wait */ ;
  591.         /* reset bit 3 of the tsr */
  592.         *tsr_ptr &= (unsigned char)~8;
  593.  
  594.         Super(save_ssp);        /* Back to user Mode */
  595. }
  596.  
  597. /*
  598.  *  f l u s h i n p u t
  599.  *
  600.  *  Dump all pending input to clear stacked up NACK's.
  601.  */
  602. flushinput()
  603. {
  604.         /* TOS Clear AUX receive buffer */
  605.         while (Cauxis())
  606.                 Cauxin();
  607. }
  608.